import sys, os

from OCC.Core import STEPCAFControl
from OCC.Core.Tesselator import ShapeTesselator
from OCC.Display.SimpleGui import init_display
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCone
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeFace
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Section, BRepAlgoAPI_Cut, BRepAlgoAPI_Fuse

os.chdir(os.path.dirname(os.path.abspath(__file__)))
from OCC.Core.BRepBndLib import brepbndlib_Add
from OCC.Core.Bnd import Bnd_Box
from OCC.Core.gp import gp_Dir, gp_Pnt, gp_Pln
from OCC.Core.gp import gp_Pnt, gp_Ax1, gp_Dir, gp_Circ, gp_Elips, gp_Trsf, gp_Vec
from OCC.Core.TopLoc import TopLoc_Location
from OCC.Core.BRepFilletAPI import BRepFilletAPI_MakeFillet, BRepFilletAPI_MakeChamfer
from OCC.Extend.DataExchange import export_shape_to_svg, read_step_file
from OCC.Extend.TopologyUtils import (TopologyExplorer, discretize_edge, get_sorted_hlr_edges,
                                      list_of_shapes_to_compound)
from OCC.Extend.DataExchange import read_step_file
from OCC.Core.BRep import BRep_Tool
from OCC.Extend.ShapeFactory import make_vertex, make_edge, midpoint
from OCC.Extend.TopologyUtils import (TopologyExplorer, list_of_shapes_to_compound,
                                      is_edge)
from OCC.Core.TopTools import TopTools_IndexedMapOfShape
from OCC.Core.Quantity import (Quantity_Color, Quantity_TOC_RGB, Quantity_NOC_WHITE,
                               Quantity_NOC_BLACK, Quantity_NOC_BLUE1,
                               Quantity_NOC_CYAN1, Quantity_NOC_RED,
                               Quantity_NOC_GREEN, Quantity_NOC_ORANGE, Quantity_NOC_YELLOW)
from OCC.Extend.TopologyUtils import is_edge, is_face
from OCC.Extend.ShapeFactory import recognize_face
from OCC.Core.gp import gp_Pnt, gp_Ax1, gp_Dir, gp_Circ, gp_Elips, gp_Trsf, gp_Vec
# help(TopTools_IndexedMapOfShape)

# import OCC
# print(OCC)
# sys.exit()

import wx
from OCC.Core.BRepAdaptor import BRepAdaptor_Surface


class MyFrame(wx.Frame):

    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)

        self.InitUI()
        # self.label_edge_id = None

    def InitUI(self):
        panel = wx.Panel(self)
        # wx.Button(self.panel, label = str(123))
        self.SetWindowStyle(wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP)
        self.label_edge_id = wx.StaticText(panel,
                                           label="ID ",
                                           pos=(5, 5), size=(-1, 32), style=wx.ALIGN_LEFT)
        self.label_edge_input = wx.TextCtrl(panel,
                                            pos=(5 + 100, 5), size=(-1, 32), style=wx.ALIGN_LEFT
                                            )
        # # 标注类型
        # self.label_dim_type = wx.StaticText(panel,
        #     label = "标注类型 ",
        #         pos=(5,45),size=(-1,32),style=wx.ALIGN_LEFT)

        # wx.ComboBox(panel, -1, pos=(5 + 100, 45), size=(-1, 32), 
        #             choices=["", "水平标注线", "垂直标注线"], style=wx.CB_READONLY)

        self.Bind(wx.EVT_CLOSE, self.On_EVT_CLOSE)

        self.SetSize((350, 250))
        self.SetTitle('Move event')
        self.Centre()

    def set_edge_id(self, idx):
        self.label_edge_input.SetValue(str(idx))

    def On_EVT_CLOSE(self, e):
        self.Hide()





# sys.exit()

# def key_down(key):
#     """
#     函数功能：按下按键
#     参    数：key:按键值
#     """
#     key = key.upper()
#     vk_code = ord(key)
#     win32api.keybd_event(vk_code,win32api.MapVirtualKey(vk_code,0),0,0)

# def print_xy_click(shp, *kwargs):
#     for shape in shp:
#         print("Shape selected: ", shape)
#     print(kwargs)
def tess_shape(shape):
    #  解析OCC方法（离散）
    tess = ShapeTesselator(shape)
    tess.Compute(compute_edges=True, mesh_quality=0.5, parallel=True)
    vertices_position = tess.GetVerticesPositionAsTuple()
    vertices_normal = tess.GetNormalsAsTuple()
    edges = []
    for edge_number in range(tess.ObjGetEdgeCount()):
        single_edge = []
        for vertex_number in range(tess.ObjEdgeGetVertexCount(edge_number)):
            edge_vertices = tess.GetEdgeVertex(edge_number, vertex_number)
            for coord in edge_vertices:
                single_edge.append(coord)
        edges.append(single_edge)

    return vertices_position, vertices_normal, edges


def compute_bbox(shp, *kwargs):
    # print("Compute bbox for %s " % shp)
    print("shp", shp)
    if len(shp) != 1: return
    shp = shp[0]
    # win = MyFrame(None,title = "Edge", size=(410,335))
    # bkg = wx.Panel(win)

    idx = edges_map.FindIndex(shp)
    if is_edge(shp):
        pre = "Edge_"
    elif is_vertex(shp):
        pre = "Vertex_"
    else:
        pre = "Face_"
    win.set_edge_id(pre + str(idx))
    a, b, c = tess_shape(shp)
    print(c)
    # loadButton = wx.Button(bkg, label = str(idx))
    win.Show()

    # for shape in shp:
    #     bbox = Bnd_Box()
    #     brepbndlib_Add(shape, bbox)
    #     xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
    #     dx = xmax - xmin
    #     dy = ymax - ymin
    #     dz = zmax - zmin
    #     print("Selected shape bounding box : dx=%f, dy=%f, dz=%f." % (dx, dy, dz))
    #     print("               bounding box center: x=%f, y=%f, z=%f" % (xmin + dx/2.,
    #                                                                     ymin + dy/2.,
    #                                                                     zmin + dz/2.))


class Solid(object):
    def __init__(self, shape=None):
        self.shape = shape

    def edges(self):
        exp = TopologyExplorer(self.shape)
        arr = list(exp.edges())
        vertices = exp.vertices_from_edge(arr[0])

        for v in vertices:
            # print(v)
            aPnt = BRep_Tool.Pnt(v)
            print(aPnt.X(), aPnt.Y(), aPnt.Z())

        print("\n")
        # print(list(vertices))
        # print(len(list(vertices)))
        # v0 = list(vertices)[0]

        # print(v0)

        # 指定倒角实体

        return arr

    def __add__(self, s):
        c = BRepAlgoAPI_Fuse(self.shape, s.shape).Shape()
        return Solid(c)

    def __sub__(self, s):
        c = BRepAlgoAPI_Cut(self.shape, s.shape).Shape()
        return Solid(c)

    def Translate(self, xyz=[0, 0, 0]):
        T = gp_Trsf()
        T.SetTranslation(gp_Vec(xyz[0], xyz[1], xyz[2]))
        loc = TopLoc_Location(T)

        self.shape.Move(loc)
        return self


class Box(Solid):
    def __init__(self, x, y, z):
        self.shape = BRepPrimAPI_MakeBox(x, y, z).Shape()


class Cone(Solid):
    def __init__(self, r1, r2, h=None):
        if h is None:
            self.shape = BRepPrimAPI_MakeCone(r1, 0, r2).Shape()
        else:
            self.shape = BRepPrimAPI_MakeCone(r1, r2, h).Shape()


# box = Box(6, 6, 3).Translate([-2, -2, 0])
# # my_box = box - Cone(0.5, 3)
# # my_box = my_box.shape

from OCC.Extend.DataExchange import *
from OCC.Extend.TopologyUtils import *
from OCC.Extend.ShapeFactory import *


def select(my_box):
    my_box = read_step_file("./T_piece.stp")
    print(11111111111, my_box)
    # x_rotate = rotate_shape(my_box, axis=gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0)), angle=180)
    # y_rotate = rotate_shape(x_rotate, axis=gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0, 1, 0)), angle=90)
    # z_rotate = rotate_shape(my_box, axis=gp_Ax1(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), angle=180)
    # write_step_file(z_rotate, "data/U012_006L/U012_006L_new.stp", application_protocol="AP203")
    display, start_display, add_menu, add_function_to_menu = init_display("wx")
    # print(display)
    win = MyFrame(None, title="Select", size=(410, 335))
    win.Show()
    # display.SetSelectionMode()
    # display.SetSelectionMode()
    #
    #
    # my_box = BRepPrimAPI_MakeBox(10., 20., 30.).Shape()

    # add_menu("按钮")
    display.register_select_callback(compute_bbox)
    # display.SetSelectionModeEdge()
    exp = TopologyExplorer(my_box)

    vertices = exp.vertices()
    edges = exp.edges()
    faces = exp.faces()
    edges_map = TopTools_IndexedMapOfShape()
    from OCC.Core.TopExp import topexp_MapShapes
    import OCC.Core.TopAbs as ta  # Tolopolgy type enum

    topexp_MapShapes(my_box, ta.TopAbs_SHAPE, edges_map)
    topexp_MapShapes(my_box, ta.TopAbs_FACE, edges_map)
    topexp_MapShapes(my_box, ta.TopAbs_EDGE, edges_map)
    topexp_MapShapes(my_box, ta.TopAbs_VERTEX, edges_map)

    # for v in vertices:
    #     edges_map.Add(v)
    # for e in edges:
    #     edges_map.Add(e)
    # for e in faces:
    #     edges_map.Add(e)
    #

    # visible_edges, hidden_edges = get_sorted_hlr_edges(my_box,
    #         # position= gp_Pnt(0, 0, 25),
    #         direction=gp_Dir(0,0,1))
    # shape_map = TopTools_IndexedMapOfShape()
    # for topods_edge in hidden_edges:
    #     shape_map.Add(topods_edge)

    """
    edges = exp.edges()
    for e in edges:
        vertices = list(exp.vertices_from_edge(e))
        if len(vertices) >= 2:
            pnt = midpoint(BRep_Tool.Pnt(vertices[0]), BRep_Tool.Pnt(vertices[1]))
        else:
            continue
            # pnt = BRep_Tool.Pnt(vertices[0])
    
        display.DisplayMessage(pnt, "e"+str(edges_map.FindIndex(e)), height=32,
            message_color=(0,0,0)
        )
        # print(pnt)
    
    faces = exp.faces()
    for e in faces:
        bbox = Bnd_Box()
        brepbndlib_Add(e, bbox)
        xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
        pnt = gp_Pnt((xmin + xmax) / 2, (ymin + ymax) / 2, (zmin + zmax) / 2)
        display.DisplayMessage(pnt, "f"+str(edges_map.FindIndex(e)), height=32,
            message_color=(0,0,0)
        )
    
    """
    # number = edges_map.FindKey(73)
    # print("number", number)
    # kind = recognize_face(number)
    # print("surf_type is : ", kind)

    display.DisplayShape(my_box, update=True, transparency=0)
    # display.SetSelectionModeVertex()
    # display.SetSelectionModeEdge()
    display.SetSelectionModeFace()
    # display.DisplayShape(z_rotate, update=True, transparency=0)
    # display.DisplayShape(edges_map.FindKey(28), update=True, transparency=0.5)
    # my_box = BRepPrimAPI_MakeBox(20., 10., 30.).Shape()
    # display.DisplayShape(my_box, update=True)
    start_display()
# win.close()
